package sessionbean;

import entity.Item;
import entity.Price;
import entity.Wishlist;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.ConstraintViolationException;
import sessionbean.facade.PriceFacade;
import sessionbean.facade.WishlistFacade;

@Stateless
public class UpdaterSession {
    @PersistenceContext(unitName = "AmazonWishlistTrackerPU")
    private EntityManager entityManager;
    @EJB
    private WishlistFacade wishlistFacade;
    @EJB
    private PriceFacade priceFacade;
    @EJB
    private HarvesterSession harvesterSession;
    
    private static final Logger logger = Logger.getLogger(UpdaterSession.class.getName());
    
    @Schedule(hour = "*", minute = "0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55")
    public void updateWishlistsPrices() {
        logger.log(Level.INFO, "Scheduled Task: Updating wishlists.");
        for (Wishlist wishlist : wishlistFacade.findAll()) {
            updateWishlistPrices(wishlist);
        }
    }
    
    public void updateWishlistPrices(Wishlist wishlist) {
        List<Item> foundItems = harvesterSession.harvestPrices(wishlist.getUrl());
        wishlist = removeMissingItems(wishlist, foundItems);

        for (Item item : foundItems) {
            logger.log(Level.INFO, "Checking item {0}", item);
            boolean found = false;
            for (Item wishlistItem : wishlist.getItems()) {
                if (wishlistItem.getTitle().equals(item.getTitle())) {
                    wishlistItem = checkIfPriceIsNewer(wishlistItem, item.getPrices().get(0));
                    found = true;
                }
            }
            if (!found) {
                logger.log(Level.INFO, "Found new item \'{0}\', adding it to wishlist.", item);
                item.setWishlist(wishlist);
                wishlist.getItems().add(item);
            }
        }
        
        try {
            logger.log(Level.INFO, "Commiting changes to wishlist {0}.", wishlist.getId());
            getEntityManager().merge(wishlist);
        } catch (ConstraintViolationException exception) {
            System.out.println(exception.getConstraintViolations());
        }
    }  
    
    public Item checkIfPriceIsNewer(Item wishlistItem, Price foundPrice) {
        BigDecimal mostRecentPrice = priceFacade.findMostRecentPrice(wishlistItem.getId());

        if (!mostRecentPrice.equals(foundPrice.getPrice())) {
            logger.log(Level.INFO, "Found new price for \'{0}\', adding it to prices.", wishlistItem);
            foundPrice.setItem(wishlistItem);
            wishlistItem.getPrices().add(foundPrice);
        }
        return wishlistItem;
    }
    
    public Wishlist removeMissingItems(Wishlist wishlist, List<Item> foundItems) {
        logger.log(Level.INFO, MessageFormat.format("Finding items no longer in wishlist {0} of account {1} to remove.", wishlist.getId(), wishlist.getAccount().getEmail()));
        Iterator<Item> itemIterator = wishlist.getItems().iterator();
        while (itemIterator.hasNext()) {
            Item item = itemIterator.next();
            if (!foundItems.contains(item)) {
                logger.log(Level.INFO, "Item {0} no longer in wishlist, removing it.", item);
                itemIterator.remove();
            }
        }
        return wishlist;
    }
    
    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}